`include "define.v"
module bpu
(
    input   wire    [31:00]     instr,                  //  
    input   wire    [63:00]     pc,                     // 
    
    // 来自译码单元的信号
    input   wire                instr_jalr,
    input   wire    [63:00]     jalr_base_addr,         // 
    input   wire    [63:00]     jalr_offset,
    //  分支预测失败
    input   wire                branch_predic_fault,
    //  输出
    // 跳转类型
    output  reg                 jal_flag,
    output  reg                 jalr_flag,
    output  reg                 branch_flag,
    //  分支预测
	output  reg    [63:00]      branch_reserve_addr,
    //  跳转地址
    output  reg    [63:00]      jump_addr
);
    // 简单解码
    reg                 instr_jal   ;
    reg                 instr_branch;
    reg     [63:00]     jal_offset   ;
    reg     [63:00]     branch_offset;
    always @( * ) begin
        case ( instr[06:02])
            `OPCODE_BRANCH : begin
                jal_flag                =   1'b0;
                jalr_flag               =   instr_jalr;
                branch_offset           =   {{52{instr[31]}}, instr[7], instr[30:25], instr[11:8], 1'b0};
                branch_flag             =   (!(branch_predic_fault || instr_jalr)) & branch_offset[63];
                jal_offset              =   64'b0;
                jump_addr               =   {64{branch_flag}} & (pc + branch_offset);
                branch_reserve_addr     =   {64{branch_flag}} & (pc + 64'd4);
            end
            `OPCODE_JAL : begin
                branch_flag             =   1'b0;
                jal_flag                =   (!(branch_predic_fault || instr_jalr));
                jalr_flag               =   instr_jalr;
                branch_offset           =   64'b0;
                jal_offset              =   {{44{instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0};
                jump_addr               =   pc + jal_offset;
                branch_reserve_addr     =   64'b0;
            end 
            default: begin
                branch_flag             =   1'b0;
                jal_flag                =   1'b0;
                jalr_flag               =   instr_jalr;
                branch_offset           =   64'b0;
                jal_offset              =   64'b0;
                jump_addr               =   {64{instr_jalr}} & (jalr_base_addr + jalr_offset);
                branch_reserve_addr     =   64'b0;
            end
        endcase
    end
endmodule